package com.jiaai.cloud.base.weixin.util;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.jiaai.cloud.base.redis.util.RedisUtil;
import com.jiaai.cloud.base.util.HttpClientUtil;

import com.jiaai.cloud.base.util.SpringUtil;
import com.jiaai.cloud.base.weixin.menu.model.BaseMenu;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * <p>
 *
 * </p>
 * @title  ${}
 * @author 佳爱网络科技
 * @version V1.0
 * @since 2017-7-10
 */
public class WeiXinUtil {

	/**
	 * 网页授权连接
	 */
	private static final String  OAUTH2URL="https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
	
	/**
	 * 根据OPENID获取授口代码
	 */
	private static final  String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
	
	/**
	 * 网页获取授权接口
	 */
	private static final String OAUTHToken="https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	
	/**
	 * 菜单API接口
	 */
	private static final  String menu_Api = " https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
	
	/**
	 * 通过openId获取用户信息
	 */
	private static final String USER_INFO_OPENID="https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	
	
	private static final String WEIXIN_APP_SESSION_KEY="https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
	
	private static Logger log= LoggerFactory.getLogger(WeiXinUtil.class);
	
	/**
	 * 获取授权连接
	 * @param appId
	 * @param redirectUri
	 * @param scope
	 * @param state
	 * @return
	 */
	public static String getOAUTH2URL(String appId,String redirectUri,String scope,String state){
		String oauthurl=OAUTH2URL.replace("APPID", appId);
		oauthurl=oauthurl.replace("SCOPE", scope);
		if(StringUtils.isEmpty(state)){
			oauthurl=oauthurl.replace("&state=STATE", "");
		}else{
			oauthurl=oauthurl.replace("STATE", state);
		}
		return oauthurl.replace("REDIRECT_URI", redirectUri);
		
	}
	
	
	/**
	 * 获取网页面授
	 * @param appId
	 * @param appsecret
	 * @param code
	 * @return
	 */
	public static OauthToken getOAuth2Token(String appId, String appsecret, String code, String scope){
		String oauthToken=OAUTHToken.replace("APPID", appId);
		oauthToken=oauthToken.replace("SECRET", appsecret);
		oauthToken=oauthToken.replace("CODE", code);
		oauthToken=oauthToken.replace("SCOPE", scope);
		JSONObject jsonObject = HttpClientUtil.httpsRequest(oauthToken, "GET", null);
		String jsons=jsonObject.toJSONString();
		OauthToken token=JSONObject.parseObject(jsons, OauthToken.class);
	
		return token;
	}
	
	/**
     * 获取接口访问凭证
     * 
     * @param appid 凭证
     * @param appsecret 密钥
     * @return
     */
    public static Token getToken(String appid, String appsecret) {
        Token token = null;
        String requestUrl = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
        RedisUtil redisUtil=getRedisUtil();
        if(redisUtil!=null){
        	String tokens=redisUtil.getString(0, "weixinToken");
        		return JSONObject.parseObject(tokens, Token.class);
        }
        // 发起GET请求获取凭证
        JSONObject jsonObject = HttpClientUtil.httpsRequest(requestUrl, "GET", null);
        if (null != jsonObject) {
            try {
                token = new Token();
                token.setAccessToken(jsonObject.getString("access_token"));
                token.setExpiresIn(jsonObject.getInteger("expires_in"));
                if(redisUtil!=null){
                	redisUtil.set(0,"weixinToken", jsonObject.toJSONString(), token.getExpiresIn());
                }
             } catch (JSONException e) {
                token = null;
                // 获取token失败
                log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInteger("errcode"), jsonObject.getString("errmsg"));
            }
        }
        return token;
    }
	
    /**
     * 创建菜单
     * @param menu
     * @return
     */
    public static JSONObject creatMenu(String appid,String appsecret,List<BaseMenu> menu) {
    	String menuUrl=menu_Api.replace("ACCESS_TOKEN", getToken(appid, appsecret).getAccessToken());
      JSONObject object=new JSONObject();
      object.put("button", menu);
        // 发起GET请求获取凭证
        JSONObject jsonObject = HttpClientUtil.httpsRequest(menuUrl, "POST", object.toJSONString());
        log.info("创建菜单[{}]",jsonObject.toJSONString());
        
        return jsonObject;
    }
	
    /**
     * 通过openId获取用户信息
     * @param openId
     * @return
     */
    public static JSONObject getUserInfoByOpenId(String appid,String appsecret,String openId)throws Exception{
    	String apiUrl=USER_INFO_OPENID.replace("ACCESS_TOKEN", getToken(appid, appsecret).getAccessToken());
    	apiUrl=apiUrl.replace("OPENID", openId);
    	JSONObject jsonObject= HttpClientUtil.httpsRequest(apiUrl, "GET", null);
    	if(jsonObject.containsKey("errcode")||jsonObject.getString("subscribe").equals("0")){
    		throw new Exception("获取用户信息失败:"+jsonObject.toJSONString());
    	}
    	return jsonObject;
    }
    
    public static JSONObject getSESSIONKEY(String appid,String secret,String js_code){
    	String url=USER_INFO_OPENID.replace("APPID",appid).replace("SECRET", secret).replace("JSCODE", js_code);
    	JSONObject jsonObject= HttpClientUtil.httpsRequest(url, "GET", null);
    	return jsonObject;
    }

	/**
	 * 获取绶存中的session
	 * @param cacheKey
	 */
	public static JSONObject getCacheSession(String cacheKey)throws  Exception {
		String values="";
		try {
			 values=getRedisUtil().hashGet(0,"app_session_key",cacheKey);
		}catch (Exception e){
			throw  new Exception("读取绶存失败");
		}
		if(StringUtils.isEmpty(values)){
			throw  new Exception("session_key 已过期");
		}
		JSONObject object=JSONObject.parseObject(values);
		return object;
	}

	/**
	 * 通过小程序获取的code获取session_token ,并保存到redis绶存中
	 * 3dr_session 为绶存中的key值
	 */
    public  static Map<String,Object>  getAppSessionKey(String appId, String appsecret, String code)throws Exception{
		String url=WEIXIN_APP_SESSION_KEY.replace("APPID",appId).replace("SECRET",appsecret).replace("JSCODE",code);
	    JSONObject jsonObject= HttpClientUtil.httpsRequest(url, "GET", null);
		if(jsonObject.containsKey("errcode")){
			throw new Exception("获取session_key异常:"+jsonObject.toJSONString());
		}
		Map<String,String> datas=new HashMap<>();
		datas.put("openid",jsonObject.get("openid").toString());
		datas.put("session_key",jsonObject.get("session_key").toString());
		datas.put("expires_in",jsonObject.getString("expires_in"));
		datas.put("create_time",String.valueOf(new Date().getTime()));
		Map<String,Object> map=new HashMap();
		map.put("session",jsonObject);
		return map;
	}
    
    private static RedisUtil getRedisUtil(){
    	return SpringUtil.getBean(RedisUtil.class);
    }
}
